
from feature import Feature, FeatureParser, registerFeatureParserClass

_issuedQualWarning = False

class SortedSummaryFeature(Feature):

  def __init__(self, *args):
    Feature.__init__(self, *args)
    self.details = False
    self.fragmentEndpoints = False

  def getLaneId(self):
    self.getDetails()
    return "%s.%s" % (self.flowcell, self.id[0])

  def getFragmentSpan(self):
    (X, Y) = self.getFragmentEndpoints()
    if X==None:
      return "%s:?-%ld" % (self.chr, Y)
    elif Y==None:
      return "%s:%ld-?" % (self.chr, X)
    else:
      return "%s:%ld-%ld" % (self.chr, X, Y)

  def getReadEndpoints(self):

    self.getDetails()
    minpos = self.spos
    maxpos = self.epos
    if self.spliceInterval:
      (chr, ival) = tuple(self.spliceInterval.split(":"))
      (spliceMin, spliceMax) = tuple(ival.split("-"))
      minpos = min(long(spliceMin), minpos)
      maxpos = max(long(spliceMax), maxpos)
    return (minpos, maxpos)

  def getFragmentEndpoints(self):
    
    self.getDetails()
    if self.fragmentEndpoints:
      return self.fragmentEndpoints

    (minpos, maxpos) = self.getReadEndpoints()

    if self.matepairInterval and self.matepairInterval != "NM":
      (chr, ival) = tuple(self.matepairInterval.split(":"))
      if chr == self.chr:
        # treat matepair on different chromosome as unmapped
        (mateMin, mateMax) = tuple(ival.split("-"))
        minpos = min(long(mateMin), minpos)
        maxpos = max(long(mateMax), maxpos)
        self.fragmentEndpoints = (minpos, maxpos)

    if not self.fragmentEndpoints:
      if self.strand == '+':
        self.fragmentEndpoints = (minpos, None)
      else:
        self.fragmentEndpoints = (None, maxpos)

    return self.fragmentEndpoints
      
  def getDetails(self):

    global _issuedQualWarning
    if self.details:
      return self
    
    cols = [x.strip() for x in self.content.split("\t")]

    phredQuals = None
    spliceInterval = ""
    matepairInterval = ""
    qual = "NA"
    qualCounts = "1"
    flowcell = ""
    libraryId = ""
    
    if len(cols)==12:
      (chr, strand, spos, epos, id, seq, startDrop, endDrop, idOk, ubOk, qual, qualCounts) = tuple(cols)
    #elif len(cols)==14:
    #  (chr, strand, spos, epos, id, seq, startDrop, endDrop, idOk, ubOk, qual, qualCounts, matepair, matepairSeq) = tuple(cols)
    elif len(cols)==10:
      (chr, strand, spos, epos, id, seq, startDrop, endDrop, idOk, ubOk) = tuple(cols)
    elif len(cols)==15:
      (chr, strand, spos, epos, id, seq, startDrop, endDrop, idOk, ubOk, qual, qualCounts, phredQuals, spliceInterval, matepairInterval) = tuple(cols)
    elif len(cols)==16:
      (chr, strand, spos, epos, id, seq, startDrop, endDrop, idOk, ubOk, qual, qualCounts, phredQuals, spliceInterval, matepairInterval, flowcell) = tuple(cols)
    elif len(cols)==17:
      (chr, strand, spos, epos, id, seq, startDrop, endDrop, idOk, ubOk, qual, qualCounts, phredQuals, spliceInterval, matepairInterval, flowcell, libraryId) = tuple(cols)
    else:
      raise Exception("expected 10, 12, or 15-17 columns... found %d... bad summary file format?" % len(cols))

    self.strand = strand
    self.id = id
    self.seq = seq
    self.startDrop = startDrop
    self.endDrop = endDrop
    self.idOk = idOk
    self.ubOk = ubOk
    self.qual = qual
    self.qualCounts = qualCounts
    self.phredQuals = phredQuals
    self.spliceInterval = spliceInterval
    self.matepairInterval = matepairInterval
    self.flowcell = flowcell
    self.libraryId = libraryId
    
    if self.qual == "NA" and self.ubOk != "Y" and not _issuedQualWarning:
      _issuedQualWarning = True
      print >> sys.stderr, "Warning! sorted summary feature from file missing quality columns.  Rows not marked as 'unique best' should be discarded..."

    self.details = True
    return self

class SortedSummaryFeatureParser(FeatureParser):
  '''
  Parser for lines in bowtie_sorted_summary.txt files.
  Parses tab-separated string:
  chr1    +       4786    4817    ...
  '''
  def parse(self, line):
    if line == None or line.startswith("#"): return None
    cols = [x.strip() for x in line.split("\t")]
    if len(cols)<4: return None
    return SortedSummaryFeature(cols[0], cols[2], cols[3], line)
  def getMaxFeatureSize(self):
    return 100
  def getFeatureType(self):
    return "SortedSummary"

registerFeatureParserClass("bowtie_sorted_summary", SortedSummaryFeatureParser)

